package com.example.malllocationserver.utils;



import com.example.malllocationserver.entity.data.Data;

import java.util.*;

//Wifi是存在数据库中的Wifi指纹，target是由手机获取的Wifi信息



public class location {

    public List<Map<String,Integer>> Wifi = new ArrayList<>();//数据库中存储的Wifi指纹
    public List<String> Type = new ArrayList<>();//数据库中Wifi指纹对应的类型（教室）
    public Map<String,Integer> zl =new HashMap<>();
    public Map<String,Integer> target;//设备检测到的Wifi信号强度
    public Split sp = new Split();//用于切割数据库中获取到的字符串型的信号信息
    public Map<String , double[]> ch = new HashMap<>();//数据库中存储的地点信息与地磁载体坐标的对应
    public Map<String , float[]> coordinate = new HashMap<>();
    private String Wifidata;//设备接受到的Wifi信号，字符串
    private String Load;//设备接受到的地磁坐标信号
    private List<double[]> target_load = new ArrayList<>();//设备接受到的地磁坐标信号，字符串
    private List<Data> data;//收到的信息，为Data类型，存着Wifi信号，地点信息，类型信息，地磁坐标信息
    private double[] max;
    private double[] min;
    private List<Map<String,Integer>> zl_data = new ArrayList<>();
    private List<String> zl_name = new ArrayList<>();
    public operation op = new operation();

    public location(List<Data> data, String Wifidata , String Load){
        this.Wifidata = Wifidata;
        this.Load = Load;
        this.data = data;
        setTarget();//初始化Target
        setType();//初始化Type
        setWifi();//初始化Wifi
        setLoad();//初始化ch
        setZl_list();//初始化走廊数据
        setTargetload();//初始化Target_load
    }
    //利用字符串切割的方法将设备检测到的wifi信号的字符串转换成Map
    public void setTarget(){
        target = sp.WifiSplit(Wifidata);
    }

    //将接收到的Data信号对应的类型存入列表
    public void setType(){
        for (Data _data : data)
            Type.add(_data.getPosition());
    }

    //通过处理Data的信息形成Wifi map列表
    public void setWifi(){
        for(Data _data : data){
            Wifi.add(sp.WifiSplit(_data.getWifi()));
        }
    }

    //初始化ch列表
    //初始化max和min列表，分别获取load值的最大值和最小值
    public void setLoad(){
        String position = classify();
        double[] load = new double[3];
        max =new double[]{0,0,0};
        min =new double[]{1000,1000,1000};
        String node = null;
        for(Data _data : data){
            if(Objects.equals(_data.getPosition(), position)&&!Objects.equals(_data.getPosition().split("_")[0],"zl")) {
                load = sp.LoadSplit(_data.getGlobal());
                for(int i=0;i<3;i++){
                    if(load[i]>max[i])
                        max[i] = load[i];
                    if(load[i]<min[i])
                        min[i] = load[i];
                }
            }
        }
        for(Data _data : data){
            if(Objects.equals(_data.getPosition(), position)){
                load = sp.LoadSplit(_data.getGlobal());
                for(int i=0;i<3;i++)
                    load[i] = nor(max[i],min[i],load[i]);
                ch.put(_data.getSerial(),load);
                coordinate.put(_data.getSerial(),new float[]{_data.getX(),_data.getY()});
                zl.put(_data.getSerial(),_data.getZl());
            }
        }
    }

    public void setZl_list(){
        String name = null;
        Map<String , Integer> new_wifi = new HashMap<>();
        for(Data _data : data){
            if(Objects.equals(_data.getPosition().split("-")[0], "zl")){
                new_wifi = sp.WifiSplit(_data.getWifi());
                name = _data.getSerial();
                coordinate.put(_data.getSerial(),new float[]{_data.getX(),_data.getY()});
            }
            zl_name.add(name);
            zl_data.add(new_wifi);
        }
    }
    //归一化操作
    public double nor(double max,double min,double norm){
        double a1 = norm-min;
        double a2 = max-min;
        double a = (norm-min)/(max-min);
        return a;
    }

    //利用归一化初始化target_load
    public void setTargetload(){
        String[] Loadlist = Load.split(";");
        List<double[]> loads = new ArrayList<>();
        for(String load: Loadlist)
            loads.add(sp.LoadSplit(load));
        for(double[] load : loads)
            for(int i=0;i<3;i++){
                load[i] = nor(max[i],min[i],load[i]);
                target_load.add(load);
            }
    }

    public String zlLocation(){
       int k=5;
       String name = op.knn_wifi(zl_data,target,zl_name,k);
       return name;
    }


    //分类算法，根据Wifi指纹确定位置在哪个Type（教室）
    public String classify(){
        int k=5;
       String type = op.knn_wifi(Wifi,target,Type,k);
       return type;
    }



    //具体坐标，根据分类得到的Type，在具体的Type中根据地磁坐标获取具体的点位
    public String acc_location(List<double[]> target){
        String _name = null;
        Map<String , Integer> name_count = new HashMap<>();
        for(int i=0;i<target.size();i++){
            _name = op.nn_load(ch,target.get(i));
            if(name_count.containsKey(_name))
                name_count.put(_name,name_count.get(_name)+1);
            else
                name_count.put(_name,1);
        }
        List<String> nameList = new ArrayList<>(name_count.keySet());
        int max = 0;
        for(String name : nameList){
            if(name_count.get(name)>=max){
                _name = name;
                max = name_count.get(name);
            }
        }
        return _name;
    }



     //将分类得到的Type与具体坐标获得的点位组合成为一个完整的坐标
    public String[] getLocation(){
        Map<String,Integer> name_count = new HashMap<>();
        if(Objects.equals(classify().split("_")[0], "zl"))
            return new String[]{classify(),zlLocation()};
        else
            return new String[]{classify(), acc_location(target_load)};
    }

    public float[] getCoordinate(){
        String name = getLocation()[1];
        float[] _coordinate = new float[3];
        _coordinate[0] = coordinate.get(name)[0];
        _coordinate[1] = coordinate.get(name)[1];
        _coordinate[2] = zl.get(name);
        return _coordinate;
    }
}